package storage.buffer;

import storage.file.Block;

public class BufferMgr {
	private static final long MAX_TIME = 10000; // 10 seconds
	private BasicBufferMgr bufferMgr;
	long waittime;

	public BufferMgr(int numbuffers) {
		bufferMgr = new BasicBufferMgr(numbuffers);
	}

	public synchronized Buffer pin(Block blk) {
		try {
			long starttime = System.currentTimeMillis();
			Buffer buff = bufferMgr.pin(blk);
			waittime = System.currentTimeMillis() - starttime;
			while (buff == null && waittime < MAX_TIME) {
				wait(MAX_TIME);
				buff = bufferMgr.pin(blk);
			}
			if (buff == null) {
				throw new BufferAbortException();
			}
			return buff;
		} catch (InterruptedException e) {
			
//			System.out.println("BufferAbortException");
//			return null;
			throw new BufferAbortException();
		}
	}

	public synchronized Buffer pinNew(String filename, PageFormatter fmtr) {
		try {
			long starttime = System.currentTimeMillis();
			Buffer buff = bufferMgr.pinNew(filename, fmtr);
			waittime = System.currentTimeMillis() - starttime;
			while (buff == null && waittime < MAX_TIME) {
				wait(MAX_TIME);
				buff = bufferMgr.pinNew(filename, fmtr);
			}
			if (buff == null)
				throw new BufferAbortException();
			return buff;
		} catch (InterruptedException e) {
			throw new BufferAbortException();
		}
	}

	public synchronized void unpin(Buffer buff) {
		bufferMgr.unpin(buff);
		if (!buff.isPinned())
			notifyAll();
	}

	public void flushAll(int txnum) {
		bufferMgr.flushAll(txnum);
	}

	public int available() {
		return bufferMgr.available();
	}

}
